﻿using System;
using System.Collections.Specialized;
using System.Web.Mvc;
using ControleRepresentante.Logic.Models;
using ControleRepresentante.Logic.Repositories;
using ControleRepresentante.Logic.Statistics;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using WebSite.Controllers;
using WebSite.ViewModels.DetailsViewModels;
using Attribute = ControleRepresentante.Logic.Models.Attribute;

namespace ControleRepresentante.UnitTests.Controllers
{
    [TestClass]
    public class FabricaControllerTests : CRUDControllerTestScenarioBase<FabricaController, Fabrica, IFabricaRepository, StatisticsBase>
    {
        private Representante m_Representante;
        private const string Nome = "nome";
        private const string CNPJ = "cnpj";
        private const string InscricaoEstadual = "inscricao estadual";
        private const bool IsJolitex = true;

        protected override FabricaController CreateController(bool isRepresentante = true)
        {
            this.LoginAsAdmin();
            Guid representanteId = this.CreateRepresentante("repre", true, "repreuser");
            Guid otherRepresentanteId = this.CreateRepresentante("otherrepre", false, "other");
            IRepresentanteRepository representanteRepository = RepositoryProvider.GetRepository<IRepresentanteRepository>();
            m_Representante = representanteRepository.GetModelById(representanteId);
            Representante otherRepresentante = representanteRepository.GetModelById(otherRepresentanteId);
            new Vendedor { Nome = "a" }.Representante = otherRepresentante;
            new Vendedor { Nome = "b" }.Representante = otherRepresentante;
            if (isRepresentante)
            {
                this.Logout();
                this.LoginAs("repreuser");
            }
            return new FabricaController(RepositoryProvider, SessionConfiguration, ControllerExtensionProvider);
        }

        protected override Fabrica CreateModel()
        {
            return new Fabrica
            {
                Nome = Guid.NewGuid().ToString(),
                CNPJ = CNPJ,
                InscricaoEstadual = InscricaoEstadual,
                Representante = m_Representante
            };
        }

        protected override ActionResult Create(FabricaController controller)
        {
            return controller.Create(Nome, CNPJ, InscricaoEstadual, CreateFormCollection());
        }

        private static FormCollection CreateFormCollection()
        {
            return new FormCollection(new NameValueCollection { { "isJolitex", IsJolitex.ToString() } });
        }

        protected override void VerifyModel(Fabrica model)
        {
            Assert.AreEqual(Nome, model.Nome);
            Assert.AreEqual(CNPJ, model.CNPJ);
            Assert.AreEqual(InscricaoEstadual, model.InscricaoEstadual);
            Assert.IsNotNull(model.FabricaJolitex);
            Assert.AreEqual(IsJolitex, model.FabricaJolitex.IsJolitex);
        }

        protected override ActionResult CreateEmptyFields(FabricaController controller)
        {
            return controller.Create(String.Empty, CNPJ, InscricaoEstadual, CreateFormCollection());
        }

        protected override void VerifyModelEmptyFields(Fabrica model)
        {
            Assert.AreEqual(String.Empty, model.Nome);
            Assert.AreEqual(CNPJ, model.CNPJ);
            Assert.AreEqual(InscricaoEstadual, model.InscricaoEstadual);
            Assert.IsNotNull(model.FabricaJolitex);
            Assert.AreEqual(IsJolitex, model.FabricaJolitex.IsJolitex);
        }

        protected override ActionResult CreateDuplicatedModel(FabricaController controller, Fabrica model)
        {
            return controller.Create(model.Nome, CNPJ, InscricaoEstadual, CreateFormCollection());
        }

        protected override void VerifyDuplicatedModel(Fabrica originalModel, Fabrica duplicatedModel)
        {
            Assert.AreEqual(originalModel.Nome, duplicatedModel.Nome);
            Assert.AreEqual(CNPJ, duplicatedModel.CNPJ);
            Assert.AreEqual(InscricaoEstadual, duplicatedModel.InscricaoEstadual);
            Assert.IsNotNull(duplicatedModel.FabricaJolitex);
            Assert.AreEqual(IsJolitex, duplicatedModel.FabricaJolitex.IsJolitex);
        }

        protected override ActionResult Edit(FabricaController controller)
        {
            return controller.Edit(Nome, CNPJ, InscricaoEstadual, CreateFormCollection());
        }

        protected override ActionResult EditEmptyFields(FabricaController controller)
        {
            return controller.Edit(String.Empty, CNPJ, InscricaoEstadual, CreateFormCollection());
        }

        protected override ActionResult EditDuplicatedModel(FabricaController controller, Fabrica modelToDuplicate)
        {
            return controller.Edit(modelToDuplicate.Nome, CNPJ, InscricaoEstadual, CreateFormCollection());
        }

        [TestMethod]
        public void TestCreateAndDeleteFullFabrica()
        {
            this.LoginAsAdmin();
            this.CreateRepresentante("my representante", true, "user");
            this.Logout();

            this.LoginAs("user");
            this.CreateAttribute(AttributeType.Fabrica, "my attribute");
            Fabrica fabrica = new Fabrica
            {
                Nome = "nome",
                CNPJ = "cnpj",
                InscricaoEstadual = "inscricao estadual",
            };
            fabrica.AddEndereco(new Endereco
            {
                Bairro = "bairro",
                CEP = "cep",
                Cidade = "cidade",
                Complemento = "complemento",
                Estado = "estado",
                Numero = "numero",
                Observacao = "observacao",
                Rua = "rua",
                Tipo = EnderecoType.Residencial,
                Principal = true
            });
            fabrica.AddConta(new Conta
            {
                Agencia = "agencia",
                Banco = "banco",
                Numero = "numero",
                Observacao = "observacao",
                Principal = true
            });
            fabrica.AddContato(new Contato
            {
                Tipo = ContatoType.FaxResidencial,
                Valor = "my contato valor",
                Observacao = "my contato observacao",
                Principal = true
            });
            fabrica.AddAttributeValue(new AttributeValue
            {
                Attribute = new Attribute { Name = "my attribute" },
                Value = "my attribute value"
            });
            Guid fabricaId = this.CreateFabrica(fabrica);
            this.DeleteFabrica(fabricaId);
        }

        [TestMethod]
        public void TestUnableToDeleteFabricaWithPedido()
        {
            this.LoginAsAdmin();
            this.CreateRepresentante("repre", true, "u");
            this.Logout();
            this.LoginAs("u");
            Guid vendedorId = this.CreateVendedor("vendedor");
            Guid clienteId = this.CreateCliente("nome", vendedorId);
            Guid transportadoraId = this.CreateTransportadora("transportadora");
            Guid fabricaId = this.CreateFabrica("fabrica");
            this.CreatePedido(vendedorId, clienteId, transportadoraId, fabricaId);
            using (FabricaController controller = new FabricaController(RepositoryProvider, SessionConfiguration, ControllerExtensionProvider))
            {
                ActionResult actionResult = controller.Delete(fabricaId);
                Assert.IsInstanceOfType(actionResult, typeof(ViewResult));
                ViewResult viewResult = (ViewResult)actionResult;
                Assert.IsInstanceOfType(viewResult.Model, typeof(DetailsViewModel));
                DetailsViewModel detailsViewModel = (DetailsViewModel)viewResult.Model;
                Assert.IsNotNull(detailsViewModel.Message);
            }
        }
    }
}